#ifndef COLLECTIONS_H
#define COLLECTIONS_H
#include <stdint.h>
#include "hashlib.h"
#define BETA
#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER)
#endif
#ifndef container_of
#define container_of(ptr, type, member) ({          \
        const typeof( ((type *)0)->member ) *__mptr = (const typeof( ((type *)0)->member ) *)(ptr); \
        (type *)( (char *)__mptr - offsetof(type,member) ); })
#endif

typedef char *str;

#if nextVersion

typedef union UType
{
	int8_t vi8;
	char vchar;
	int16_t vi16;
	short vshort;
	int32_t vi32;
	int vint;
	float vfloat;

	int8_t *pi8;
	char *pchar;
	int16_t *pi16;
	short *pshort;
	int32_t *pi32;
	int *pint;
	int64_t *pi64;
	long *plong;
	float *pfloat;
	double *pdouble;
	void *pvoid;
#ifdef UType_ENABLE_x64
	int64_t vi64;
	long vlong;
	double vdouble;
#endif
} UType;

#endif

#pragma region ln_list
typedef struct Ln_list_t
{
	struct Ln_list_t *next;
} Ln_list_t;
typedef Ln_list_t *Ln_list;
typedef Ln_list Ln_head;

int ln_list_add(Ln_head list, Ln_list new_node);
int ln_list_add_tail(Ln_head list, Ln_list new_node);
int ln_list_remove(Ln_head list, Ln_list node);
int ln_list_move(Ln_head list, Ln_list node);
int ln_list_move_tail(Ln_head list, Ln_list node);
#pragma endregion

#pragma region obj
typedef struct _NameTuple_t
{
	char *name;
	HASH hashCode;
} _NameTuple_t;
typedef _NameTuple_t *_NameTuple;

// int __nameTuple_compare(const void *a, const void *b);
int public_obj(Li_List list, void *new_obj);
int search_obj(Li_List list, const char *name);

#pragma endregion

#pragma region cmdline, etc.

typedef struct
{
	union
	{
		_NameTuple_t nameTuple;
		struct
		{
			char *name;
			HASH hashCode;
		};
	};
	const char *annotation;
	Cmdline_def todo;
} Cmd_t;

typedef union
{
	float vf;
	int32_t vi;
	str vs;
	unsigned char vc;
	void *pvoid;
	float *pf;
	int32_t *pi;
	str *ps;
	char *pc;
} Val;

#define VarType_float 'f'
#define VarType_int 'i'
#define VarType_char 'c'
#define VarType_str 's'

typedef struct
{
	union
	{
		_NameTuple_t nameTuple;
		struct
		{
			char *name;
			HASH hashCode;
		};
	};
	Val val;
	char type;		   // type symbol, 'f':float, 'd':int32_t, 'c':char
	unsigned char len; // length of this array, only when isp==1
	char isb : 1;	   // is built in variable? that means this var cannot be changed in type
	char isp : 1;	   // is ref a pointer or a value?
	char isa : 1;	   // is ref a array?
} Var_t;

typedef struct
{
	union
	{
		_NameTuple_t nameTuple;
		struct
		{
			char *name;
			HASH hashCode;
		};
	};
	void *ref;			// value, a pointer to a function
	unsigned char narg; // number of arg
	char type;			// arguments type kind
} Fun_t;

typedef Var_t *Var;
typedef Cmd_t *Cmd;
typedef Fun_t *Fun;

#pragma endregion

#pragma region pipe

typedef void *(*PipeLine)(void *obj, char *msg, int32_t len);
typedef struct Pipe_t
{
	const char *id;
	void *arg;
	struct Pipe_t *next, *priv;
	PipeLine out;
} Pipe_t;
typedef Pipe_t *Pipe;
#pragma endregion

typedef struct
{
	Li_List cmds, funs, vars;
	Pipe BETA lily_std_pipe;
	int32_t BETA open_time;
	int32_t BETA r_count;
	int32_t BETA rtc;
	float BETA rtcf;
	const char *BETA _error_msg, *_error_loc;
	Cmdline_def BETA hijacker_callback;
	Tasks_def BETA _cmd_done_listener;

	// int32_t cmd_queue_in_waitting;
	// char *rx;
	// char *_cmd;
	// int32_t rx_length;
	// int32_t hi, ri;
	// int32_t max_cmd_len;

	// flag bits
	char BETA is_busy : 1;
	// char hijacked : 1;
	char BETA _echo : 1;
} LilyUI_t;
typedef LilyUI_t *LilyUI;

#endif